home *** CD-ROM | disk | FTP | other *** search
/ MacWorld 1998 March / Macworld (1998-03) (Disk 1).dmg / Shareware World / Info / For Developers / GhostScript 5.10 / MacGS-510 / files / gs_pdf.ps < prev    next >
Text File  |  1997-09-27  |  20KB  |  647 lines

  1. %    Copyright (C) 1994, 1996, 1997 Aladdin Enterprises.  All rights reserved.
  2. % This file is part of Aladdin Ghostscript.
  3. % Aladdin Ghostscript is distributed with NO WARRANTY OF ANY KIND.  No author
  4. % or distributor accepts any responsibility for the consequences of using it,
  5. % or for whether it serves any particular purpose or works at all, unless he
  6. % or she says so in writing.  Refer to the Aladdin Ghostscript Free Public
  7. % License (the "License") for full details.
  8. % Every copy of Aladdin Ghostscript must include a copy of the License,
  9. % normally in a plain ASCII text file named PUBLIC.  The License grants you
  10. % the right to copy, modify and redistribute Aladdin Ghostscript, but only
  11. % under certain conditions described in the License.  Among other things, the
  12. % License requires that the copyright notice and this notice be preserved on
  13. % all copies.
  14.  
  15. % gs_pdf.ps
  16. % ProcSet for PostScript files created by the PDF to PostScript converter.
  17. % This ProcSet requires only a Level 1 interpreter, unless fonts other
  18. % than ordinary Type 1 or Type 3 fonts are involved.
  19.  
  20. % pdf2ps copies this file from %BEGIN to the end.
  21.  
  22. %BEGIN
  23. % Patches for Level 1 printers and non-Ghostscript interpreters.
  24. mark
  25. /currentglobal { false }
  26. /setglobal { pop }
  27. /packedarray { array astore readonly }
  28. /setcmykcolor {
  29.   1 exch sub
  30.   4 -1 roll 1 exch sub 1 index mul
  31.   4 -1 roll 1 exch sub 2 index mul
  32.   4 -2 roll exch 1 exch sub mul
  33.   setrgbcolor
  34. }
  35. /sethalftonephase { pop pop }
  36. /setpagedevice {
  37.   statusdict /pageparams get exec
  38.   4 index /PageSize .knownget { aload pop 6 -2 roll pop pop 4 2 roll } if
  39.   4 index /Orientation .knownget { 3 -1 roll pop exch } if
  40.   statusdict /setpageparams get exec
  41.   /PageOffset .knownget { aload pop translate } if
  42. }
  43. /setoverprint { pop }
  44. /setstrokeadjust { pop }
  45. /.copydict { dup 3 -1 roll { put dup } forall pop }
  46. /.dicttomark {
  47.   counttomark 2 idiv dup dict begin { def } repeat pop currentdict end
  48. }
  49. /.knownget { 2 copy known { get true } { pop pop false } ifelse }
  50. /.setdefaultscreen { }
  51. counttomark 2 idiv {
  52.   1 index where { pop pop pop } { bind executeonly def } ifelse
  53. } repeat pop
  54.  
  55. currentglobal true setglobal
  56.  
  57. % Define pdfmark.  Don't allow it to be bound in.
  58. % Also don't define it in systemdict, because this leads some Adobe code
  59. % to think this interpreter is a distiller.
  60. % (If this interpreter really is a distiller, don't do this.)
  61. systemdict /pdfmark known not
  62.  { userdict /pdfmark { cleartomark } bind put } if
  63.  
  64. % This ProcSet is designed so that it can be used either to execute PDF
  65. % (the default) or to convert PDF to PostScript.  See ! and ~ below.
  66.  
  67. userdict /GS_PDF_ProcSet 127 dict dup begin
  68.  
  69. % ---------------- Abbreviations ---------------- %
  70.  
  71. /bdef { bind def } bind def
  72.  
  73. % ---------------- Operator execution ---------------- %
  74.  
  75. % We record "operator" names in a dictionary with their argument counts,
  76. % so that they can easily be redefined later to write PostScript in
  77. % addition to (or instead of) being executed.
  78.  
  79. /numargsdict 100 dict def
  80. /!        % <procname> <proc> <numargs> ! -
  81.  { //numargsdict 3 index 3 -1 roll put def
  82.  } bdef
  83. /~        % <procname> <opname> <numargs> ~ -
  84.  { exch cvx 1 packedarray cvx exch !
  85.  } bdef
  86.  
  87. % ---------------- Graphics state stack ---------------- %
  88.  
  89. % PDF adds a number of parameters to the graphics state.
  90. % We implement this by pushing and popping a dictionary
  91. % each time we do a PDF gsave or grestore.
  92. % The keys in this dictionary are as follows:
  93. %    self            % identifies the dictionary as one of ours
  94. %    Show
  95. %    TextOrigin        % origin of current line, in text space
  96. %    TextSaveMatrix        % matrix at time of BT
  97. % (The following correspond directly to PDF state parameters.)
  98. %    FillColor
  99. %    FillColorSpace
  100. %    StrokeColor
  101. %    StrokeColorSpace
  102. %    TextSpacing
  103. %    TextHScaling
  104. %    Leading
  105. %    TextFont
  106. %    TextMatrix
  107. %    TextRise
  108. %    TextRenderingMode
  109. %    WordSpacing
  110.  
  111. /nodict 1 dict def
  112. nodict /self { //nodict } executeonly put
  113. nodict readonly pop
  114.  
  115. /beginpage
  116.  { //nodict 20 dict .copydict begin graphicsbeginpage textbeginpage
  117.  } bdef
  118. /endpage
  119.  { showpage end
  120.  } bdef
  121.  
  122. /graphicsbeginpage { initgraphics  0 g  0 G } bdef
  123.  
  124. /gput        % <value> <key> gput -
  125.  { exch currentdict //nodict eq { /self dup load end 5 dict begin def } if
  126.         % If we're in a Level 1 system, we need to grow the
  127.         % dictionary explicitly.
  128.    currentdict length currentdict maxlength ge %eq
  129.     { currentdict dup length 3 mul 2 idiv 1 add dict .copydict end begin 
  130.     }
  131.    if def
  132.  } bdef
  133.  
  134. /q_
  135.  { gsave //nodict begin
  136.  } bdef
  137. /q /q_ load 0 !
  138. % Some PDF files have excess Q operators!
  139. /Q_
  140.  { currentdict /self .knownget { exec //nodict eq { end grestore } if } if
  141.  } bdef
  142. /Q /Q_ load 0 !
  143.  
  144. % ---------------- Graphics state parameters ---------------- %
  145.  
  146. /d /setdash 2 ~
  147. /i /setflat 1 ~
  148. /j /setlinejoin 1 ~
  149. /J /setlinecap 1 ~
  150. /M /setmiterlimit 1 ~
  151. /w /setlinewidth 1 ~
  152.  
  153. % ---------------- Color setting ---------------- %
  154.  
  155. /fcput        % <color> <colorspace> fcput -
  156.  { /FillColorSpace gput /FillColor gput
  157.  } bdef
  158. /scput        % <color> <colorspace> scput -
  159.  { /StrokeColorSpace gput /StrokeColor gput
  160.  } bdef
  161.  
  162. /csdevgray [/DeviceGray] readonly def
  163. /csdevrgb [/DeviceRGB] readonly def
  164. /csdevcmyk [/DeviceCMYK] readonly def
  165. % Perhaps some of the values in the following need to be modified
  166. % depending on the WhitePoint value....
  167. /cslabinit mark
  168.   /DecodeABC [{16 add 116 div} bind {500 div} bind {200 div} bind]
  169.   /MatrixABC [1 1 1 1 0 0 0 0 -1]
  170.   /DecodeLMN [
  171.     {dup 6 29 div ge {dup dup mul mul} {4 29 div sub 108 841 div mul} ifelse
  172.      0.9505 mul} bind
  173.     {dup 6 29 div ge {dup dup mul mul} {4 29 div sub 108 841 div mul} ifelse
  174.      } bind
  175.     {dup 6 29 div ge {dup dup mul mul} {4 29 div sub 108 841 div mul} ifelse
  176.      1.0890 mul} bind
  177.   ]
  178. .dicttomark readonly def
  179. /nullpattern1 mark
  180.    /PatternType 1 /PaintType 1 /TilingType 3 /BBox [0 0 0 0]
  181.    /XStep 1 /YStep 1 /PaintProc { }
  182. .dicttomark readonly def
  183. /nullpattern2 nullpattern1 dup length dict copy readonly def
  184.  
  185. % Each entry in the color space dictionary is a procedure of the form
  186. %    <cspace> -proc- <initial-color> <cspace'>
  187. /CSdict 11 dict dup begin
  188.   /DeviceGray { 0 exch } bdef
  189.   /DeviceRGB { [0 0 0] cvx exch } bdef
  190.   /DeviceCMYK { [0 0 0 1] cvx exch } bdef
  191.   /Indexed
  192.    { dup 1 get csset exch pop
  193.      dup 2 index 1 get eq
  194.       { pop }
  195.       { exch 4 array copy dup 1 4 -1 roll put }
  196.      ifelse 0 exch
  197.     } bdef
  198.   /CalGray
  199.    { systemdict /setcolorrendering known
  200.       { 1 get dup /Gamma .knownget
  201.      { dup length 1 add dict .copydict
  202.        dup /DecodeA 4 -1 roll /exp load 2 packedarray cvx put
  203.      }
  204.     if /CIEBasedA exch 2 array astore 0 exch
  205.       }
  206.       { pop //csdevgray csset
  207.       }
  208.      ifelse
  209.    } bdef
  210.   /CalRGB
  211.    { systemdict /setcolorrendering known
  212.       { 1 get dup /Gamma known 1 index /Matrix known or
  213.      { dup length 2 add dict .copydict
  214.        dup /Matrix .knownget { 1 index /MatrixABC 3 -1 roll put } if
  215.        dup /Gamma .knownget
  216.         { [ exch { /exp load 2 packedarray cvx } forall
  217.           ] 1 index /DecodeABC 3 -1 roll put
  218.         }
  219.        if
  220.      }
  221.     if /CIEBasedABC exch 2 array astore [0 0 0] cvx exch
  222.        }
  223.        { pop //csdevrgb csset
  224.        }
  225.       ifelse
  226.     } bdef
  227.   /CalCMYK { pop //csdevcmyk csset } bdef    % not supported yet
  228.   /Lab
  229.    { systemdict /setcolorrendering known
  230.       { 1 get dup length 3 add dict .copydict
  231.     dup /Range .knownget not { [-100 100 -100 100] } if
  232.     [-100 0 null null null null] dup 2 4 -1 roll putinterval
  233.     1 index /RangeABC 3 -1 roll put
  234.     //cslabinit exch copy
  235.     /CIEBasedABC exch 2 array astore [0 0 0] cvx exch
  236.        }
  237.        { (****** Lab color space not supported. ******\n) print flush
  238.      /setcolorspace cvx /undefined signalerror
  239.        }
  240.       ifelse
  241.    } bdef
  242.   /Pattern
  243.    { //nullpattern1 1 index type /nametype ne
  244.       { 1 index length 0 ne { pop //nullpattern2 } if
  245.       } if
  246.      matrix makepattern exch
  247.    } bdef
  248.   /Separation { 1 exch } bdef
  249. end def
  250. /csset            % <cspace> csset <color> <cspace'>
  251.  { dup dup type /nametype ne { 0 get } if //CSdict exch get exec
  252.  } bdef
  253.  
  254. /g { //csdevgray fcput } 1 !
  255. /G { //csdevgray scput } 1 !
  256. /rg { 3 array astore cvx //csdevrgb fcput } 3 !
  257. /RG { 3 array astore cvx //csdevrgb scput } 3 !
  258. /k { 4 array astore cvx //csdevcmyk fcput } 4 !
  259. /K { 4 array astore cvx //csdevcmyk scput } 4 !
  260. /cs { csset fcput } 1 !
  261. /CS { csset scput } 1 !
  262. % We have to break up sc according to the number of operands.
  263. /sc1 { /FillColor gput } 1 !
  264. /SC1 { /StrokeColor gput } 1 !
  265. /sc2 { /FillColor gput } 2 !
  266. /SC2 { /StrokeColor gput } 2 !
  267. /sc3 { /FillColor load astore pop } 3 !
  268. /SC3 { /StrokeColor load astore pop } 3 !
  269. /sc4 { /FillColor load astore pop } 4 !
  270. /SC4 { /StrokeColor load astore pop } 4 !
  271. /sc5 { /FillColor gput } 5 !
  272. /SC5 { /StrokeColor gput } 5 !
  273.  
  274. % ---------------- Color installation ---------------- %
  275.  
  276. % Establish a given color (and color space) as current.
  277. /setfillcolor { FillColor FillColorSpace setgcolor } def
  278. /setstrokecolor { StrokeColor StrokeColorSpace setgcolor } def
  279. /CIdict mark            % only used for Level 1
  280.   /DeviceGray 1   /DeviceRGB 3   /DeviceCMYK 4
  281.   /CIEBaseA 1   /CIEBaseABC 3   /CIEBasedDEF 3   /CIEBaseDEFG 4
  282. .dicttomark def
  283. /Cdict 11 dict dup begin    % <color...> <colorspace> -proc- -
  284.   /DeviceGray { pop setgray } bdef
  285.   /DeviceRGB { pop setrgbcolor } bdef
  286.   /DeviceCMYK { pop setcmykcolor } bdef
  287.   /CIEBasedA
  288.    { dup currentcolorspace eq { pop } { setcolorspace } ifelse setcolor } bdef
  289.   /CIEBasedABC /CIEBasedA load def
  290.   /CIEBasedDEF /CIEBasedA load def
  291.   /CIEBasedDEFG /CIEBasedA load def
  292.   /Indexed /setcolorspace where
  293.    { pop /CIEBasedA load }
  294.    { /setindexedcolor cvx }
  295.   ifelse def
  296.   /Pattern
  297.    { dup currentcolorspace eq { pop } { setcolorspace } ifelse
  298.      dup /Matrix get makepattern setcolor
  299.    } bdef
  300.   /Separation /CIEBasedA load def
  301. end def
  302. /setindexedcolor        % <index> [/Indexed base hival proc|str]
  303.                 %   setindexedcolor - (only used for Level 1)
  304.  { mark 3 -1 roll
  305.    2 index 3 get    % Stack: cspace -mark- index proc|str
  306.    dup type /stringtype eq
  307.     { //CIdict 4 index 1 get 0 get get        % # of components
  308.       dup 4 -1 roll mul exch getinterval { 255 div } forall
  309.     }
  310.     { exec
  311.     }
  312.    ifelse
  313.    counttomark 2 add -2 roll pop
  314.    1 get setgcolor
  315.  } bdef
  316. /setgcolor    % (null | <color...>) <colorspace> setgcolor -
  317.  { 1 index null eq
  318.     { pop pop }
  319.     { dup 0 get //Cdict exch get exec }
  320.    ifelse
  321.  } bdef
  322. /fsexec        % <fillop|strokeop> fsexec -
  323.  {        % Preserve the current point, if any.
  324.     { currentpoint } stopped
  325.     { $error /newerror false put   cvx exec }
  326.     { 3 -1 roll cvx exec moveto }
  327.    ifelse
  328.  } bdef
  329.  
  330. % ---------------- Transformations ---------------- %
  331.  
  332. /cmmatrix matrix def
  333. /cm { //cmmatrix astore concat } 6 !
  334.  
  335. % ---------------- Path creation ---------------- %
  336.  
  337. /m /moveto 2 ~
  338. /l /lineto 2 ~
  339. /c /curveto 6 ~
  340. /h /closepath 0 ~
  341. /v { currentpoint 6 2 roll curveto } 4 !
  342. /y { 2 copy curveto } 4 !
  343. /re
  344.  { 4 2 roll moveto  exch dup 0 rlineto  0 3 -1 roll rlineto  neg 0 rlineto
  345.    closepath
  346.  } 4 !
  347.  
  348. % ---------------- Path painting and clipping ---------------- %
  349.  
  350. /S_ { setstrokecolor /stroke fsexec } bdef
  351. /S { S_ } 0 !
  352. /f { setfillcolor /fill fsexec } 0 !
  353. /f* { setfillcolor /eofill fsexec } 0 !
  354. /n_ { newpath } bdef        % don't allow n_ to get bound in
  355. /n { n_ } 0 !
  356. /s { closepath S_ } 0 !
  357. /B_ { gsave setfillcolor fill grestore S_ } bdef
  358. /B /B_ load 0 !
  359. /b { closepath B_ } 0 !
  360. /B*_ { gsave setfillcolor eofill grestore S_ } bdef
  361. /B* /B*_ load 0 !
  362. /b* { closepath B*_ } 0 !
  363.  
  364. % Clipping:
  365.  
  366. /Wdict 4 dict dup begin
  367. /S_ { gsave setstrokecolor stroke grestore n_ } bdef
  368. /f { gsave setfillcolor fill grestore n_ } 0 !
  369. /f* { gsave setfillcolor eofill grestore n_ } 0 !
  370. /n_ { end clip newpath } bdef
  371. end readonly def
  372. /W { //Wdict begin } 0 !
  373. /W*dict 4 dict dup begin
  374. /S_ { gsave setstrokecolor stroke grestore n_ } bdef
  375. /f { gsave setfillcolor fill grestore n_ } 0 !
  376. /f* { gsave setfillcolor eofill grestore n_ } 0 !
  377. /n_ { end eoclip newpath } bdef
  378. end readonly def
  379. /W* { //W*dict begin } 0 !
  380.  
  381. % ---------------- Images ---------------- %
  382.  
  383. % We mustn't bind these now, since they reference Level 2 operators.
  384. /Is        % <imagedict> Is <imagedict> <datasource>
  385.  { dup /DataSource get string /readstring cvx /currentfile cvx
  386.         % Stack: imagedict string -readstring- -currentfile-
  387.    3 index /FilterProc .knownget
  388.     { dup dup 0 get /ASCIIHexDecode eq exch length 2 eq and
  389.        { pop exch pop /readhexstring cvx exch }
  390.        { exch exec exch exec }
  391.       ifelse
  392.     }
  393.    if 3 1 roll /pop cvx 4 packedarray cvx
  394.  } bdef
  395. /EI { } def    % placeholder, only needed when writing PostScript
  396. % Note that ID* take a dictionary, not separate values;
  397. % ColorSpace must be a name if it has no parameters;
  398. % DataSource is the size of the row buffer in bytes;
  399. % FilterProc is an optional procedure for constructing the decoding filter;
  400. % and ImageMask is required, not optional.
  401. /csimage
  402.  { /setcolorspace where
  403.     { pop dup /ColorSpace get csset setcolorspace pop image }
  404.     { .colorspaceimage }
  405.    ifelse
  406.  } def        % don't bind, because of Level 2
  407. /ID    % <imagedict> ID -
  408.  { Is dup 3 -1 roll dup /ImageMask get
  409.     { setfillcolor dup /Interpolate .knownget not { false } if
  410.        { dup /DataSource 4 -1 roll put /imagemask cvx exec
  411.        }
  412.        {  { /Width /Height /Decode /ImageMatrix }
  413.       { 1 index exch get exch }
  414.      forall pop exch 0 get 0 ne exch
  415.      5 -1 roll imagemask
  416.        }
  417.       ifelse
  418.     }
  419.     { dup /ColorSpace get /DeviceGray eq
  420.       1 index /BitsPerComponent get 8 le and
  421.       1 index /Decode get dup 1 get 1 eq exch 0 get 0 eq and and
  422.       1 index /Interpolate .knownget not { false } if not and
  423.        {  { /Width /Height /BitsPerComponent /ImageMatrix }
  424.       { 1 index exch get exch }
  425.      forall pop 5 -1 roll image
  426.        }
  427.        { dup /DataSource 4 -1 roll put csimage
  428.        }
  429.       ifelse
  430.     }
  431.    ifelse
  432.         % If we were reading with readhexstring,
  433.         % skip the terminating > now.
  434.         % Stack: datasource
  435.    dup type /filetype ne        % array or packedarray
  436.     { dup 2 get /readhexstring eq
  437.        {  { dup 0 get exec read pop (>) 0 get eq { exit } if } loop
  438.        }
  439.       if pop
  440.     }
  441.     { pop
  442.     }
  443.    ifelse EI
  444.  } 1 !
  445. % IDx handles general images.
  446. /IDx    % <imagedict> IDx -
  447.  { Is 1 index /DataSource 3 -1 roll put
  448.    csimage EI
  449.  } 1 !
  450.  
  451. % ---------------- Text control ---------------- %
  452.  
  453. /textbeginpage
  454.  { /TextSpacing 0 def        % 0 Tc
  455.    /TextLeading 0 def        % 0 TL
  456.    /TextRenderingMode 0 def    % 0 Tr
  457.    /TextRise 0 def        % 0 Ts
  458.    /WordSpacing 0 def        % 0 Tw
  459.    /TextHScaling 1.0 def    % 100 Tz
  460.    /TextFont null def
  461.    /Show { showfirst } def
  462.  } bdef
  463.  
  464. % Contrary to the statement in the PDF manual, BT and ET *can* be nested,
  465. % if the CharProc for a Type 3 font does a BT/ET itself.
  466. % Since we always call the CharProc inside a q_/Q_, we simply ensure that
  467. % the text state is saved and restored like the rest of the extended
  468. % graphics state.
  469.  
  470. /settextmatrix
  471.  { TextMatrix concat
  472.    TextHScaling 1 ne { TextHScaling 1 scale } if
  473.    TextRise 0 ne { 0 TextRise translate } if
  474.  } bdef
  475. /settextstate { TextSaveMatrix setmatrix settextmatrix } bdef
  476.  
  477. /BT
  478.  { currentdict /TextMatrix .knownget
  479.     { identmatrix pop }
  480.     { matrix /TextMatrix gput }
  481.    ifelse
  482.    currentdict /TextOrigin .knownget
  483.     { dup 0 0 put 1 0 put }
  484.     { [0 0] cvx /TextOrigin gput }
  485.    ifelse
  486.     { showfirst } /Show gput
  487.    currentdict /TextSaveMatrix .knownget not
  488.     { matrix dup /TextSaveMatrix gput }
  489.    if currentmatrix pop settextmatrix 0 0 moveto
  490.    TextFont dup null eq { pop } { setfont } ifelse
  491.  } bind 0 !
  492. /ET
  493.  { TextSaveMatrix setmatrix
  494.  } bind 0 !
  495. /Tc_ { /TextSpacing gput { showfirst } /Show gput } bdef
  496. /Tc { Tc_ } 1 !
  497. /TL { /TextLeading gput } bind 1 !
  498. /Tr { /TextRenderingMode gput { showfirst } /Show gput } bind 1 !
  499. /Ts { /TextRise gput settextstate } bind 1 !
  500. /Tw_ { /WordSpacing gput { showfirst } /Show gput } bdef
  501. /Tw { Tw_ } 1 !
  502. /Tz { 100 div /TextHScaling gput settextstate } bind 1 !
  503.  
  504. % ---------------- Font control ---------------- %
  505.  
  506. /Tf        % <font> <scale> Tf -
  507.  { dup 1 eq { pop } { scalefont } ifelse
  508.    dup setfont /TextFont gput
  509.  } 2 !
  510.  
  511. % Read a CFF font.
  512. /FRD        % <resdict> <file> FRD -
  513.  { /FontSetInit /ProcSet findresource begin ReadData
  514.  } 2 !
  515.  
  516. % Copy a font, removing its FID.  If changed is true, also remove
  517. % the UniqueID and XUID, if any.  If the original dictionary doesn't have
  518. % the keys being removed, don't copy it.
  519. /.copyfontdict        % <font> <changed> .copyfontdict <dict>
  520.  { 1 index /FID known
  521.    1 index { 2 index /UniqueID known or 2 index /XUID known or } if
  522.     {        % We add 1 to the length just in case the original
  523.         % didn't have a FID.
  524.       exch dup length 1 add dict exch
  525.        {        % Stack: changed newfont key value
  526.      1 index /FID eq 4 index
  527.       { 2 index /UniqueID eq or 2 index /XUID eq or }
  528.      if not { 3 copy put } if pop pop
  529.        }
  530.       forall exch
  531.     }
  532.    if pop
  533.  } bdef
  534.  
  535. % Insert a new Encoding or Metrics into a font if necessary.
  536. % Return a possibly updated font, and a flag to indicate whether
  537. % the font was actually copied.
  538. /.updatefont        % <font> <Encoding|null> <Metrics|null> .updatefont
  539.             %   <font'> <copied>
  540.  { 2 index 4 1 roll
  541.    dup null ne
  542.     { 3 -1 roll true .copyfontdict dup /Metrics 4 -1 roll put exch }
  543.     { pop }
  544.    ifelse
  545.    dup null ne 1 index 3 index /Encoding get ne and
  546.     { exch false .copyfontdict dup /Encoding 4 -1 roll put }
  547.     { pop }
  548.    ifelse exch 1 index ne
  549.  } bdef
  550.  
  551. % ---------------- Text positioning ---------------- %
  552.  
  553. /Td_
  554.  { TextOrigin exch 4 -1 roll add 3 1 roll add
  555.    2 copy /TextOrigin load astore pop moveto
  556.  } bdef
  557. /Td { Td_ } 2 !
  558. /TD { dup neg /TextLeading gput Td_ } 2 !
  559. /T*_ { 0 TextLeading neg Td_ } bdef
  560. /T* { T*_ } 0 !
  561. /Tm
  562.  { TextMatrix astore pop settextstate
  563.    0 0 /TextOrigin load astore pop
  564.    0 0 moveto
  565.  } 6 !
  566.  
  567. % ---------------- Text painting ---------------- %
  568.  
  569. /textrenderingprocs [        % (0 is handled specially)
  570.    { tf } { tS } { tB } { tn }
  571.     % We don't know what the clipping modes mean....
  572.    4 copy
  573. ] readonly def
  574. /setshowstate
  575.  { WordSpacing 0 eq TextSpacing 0 eq and
  576.     { TextRenderingMode 0 eq
  577.        { { setfillcolor show } }
  578.        { { false charpath textrenderingprocs TextRenderingMode get exec } }
  579.       ifelse
  580.     }
  581.     { TextRenderingMode 0 eq
  582.        { WordSpacing 0 eq
  583.           { { setfillcolor TextSpacing exch 0 exch ashow } }
  584.       { TextSpacing 0 eq
  585.          { { setfillcolor WordSpacing exch 0 exch 32 exch widthshow } }
  586.          { { setfillcolor WordSpacing exch TextSpacing exch 0 32 4 2 roll 0 exch awidthshow } }
  587.         ifelse
  588.       }
  589.      ifelse
  590.        }
  591.        { { WordSpacing TextSpacing 2 index
  592.             % Implement the combination of t3 and false charpath.
  593.             % Stack: xword xchar string
  594.        0 1 2 index length 1 sub
  595.         { 2 copy 1 getinterval false charpath
  596.             % Stack: xword xchar string i
  597.           4 copy get 32 eq { add } { exch pop } ifelse 0 rmoveto
  598.           pop
  599.         }
  600.        for pop pop pop pop
  601.        textrenderingprocs TextRenderingMode get exec
  602.      }
  603.        }
  604.       ifelse
  605.     }
  606.    ifelse /Show gput
  607.  } bdef
  608. /showfirst { setshowstate Show } def
  609.  
  610. /Tj { Show } 1 !
  611. /' { T*_ Show } 1 !
  612. /" { exch Tc_ exch Tw_ T*_ Show } 3 !
  613. % TJ expects a mark followed by arguments, not an array.
  614. /TJ
  615.  { counttomark -1 1
  616.     { -1 roll dup type /stringtype eq
  617.        { Show
  618.        }
  619.        { -1000 div
  620.      currentfont /ScaleMatrix .knownget { 0 get mul } if
  621.      0 rmoveto
  622.        }
  623.       ifelse
  624.     }
  625.    for pop
  626. % Adobe implementations don't accept /[, so we don't either.
  627.  } ([) cvn !
  628.  
  629. /tf { setfillcolor currentpoint fill moveto } bdef
  630. /tn { currentpoint newpath moveto } bdef
  631. % For stroking characters, temporarily restore the graphics CTM so that
  632. % the line width will be transformed properly.
  633. /Tmatrix matrix def
  634. /tS
  635.  { setstrokecolor
  636.    currentpoint //Tmatrix currentmatrix TextSaveMatrix setmatrix stroke
  637.    setmatrix moveto
  638.  } bdef
  639. /tB { gsave tf grestore tS } bdef
  640.  
  641. end readonly put        % GS_PDF_ProcSet
  642.  
  643. setglobal
  644.